package com.jin.webvideo.parser;

import com.alibaba.fastjson.JSONObject;
import com.jin.webvideo.entity.VideoInfo;
import com.jin.webvideo.entity.ParserParam;
import com.jin.webvideo.entity.Parser;

import com.jin.webvideo.js.stopwatch.StopwatchThread;
import com.jin.webvideo.mapper.ParserMapper;
import com.jin.webvideo.util.base.URLUtil;
import com.jin.webvideo.util.entity.EntityUtil;
import com.jin.webvideo.util.base.StringUtil;
import com.jin.webvideo.util.sys.*;
import org.graalvm.polyglot.PolyglotException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.script.ScriptException;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;

@Component
public class ParserManage {
    private static Map<String, String> config = new HashMap<>();
    @Autowired
    private ParseSourceManager sourceManager;
    @Autowired
    private ParserMapper parserMapper;
    @Autowired
    private ParserScriptPropertites builderConfig;

    /**
     * 清除所有全局变量
     * @param name
     */
    public static void clearConfig(String name){
        if (StringUtil.isEmpty(name)){
            config.clear();
            return;
        }
        config.remove(name);
    }
    public void reload(String name){
         sourceManager.clear();
    }
    // 执行scriptName文件中的methodName方法
    public ParseResult execFunc(String scriptName, String methodName, String input){
        ParseResult parseResult = null;
        try {
            ParseScriptExector scriptExector = new ParseScriptExector(sourceManager, builderConfig);
            // 更新变量
            scriptExector.eval(scriptName);
            // 获取配置信息
            String configStr = config.getOrDefault(methodName, "{}");
            // 定时器定时关闭
            StopwatchThread.newIntance().addTimeoutEvent(scriptName + "." + methodName,10000, ()-> scriptExector.close(true));
            // 获取结果
            String result = scriptExector.execFunc(scriptName, methodName, input, configStr);
            // 关闭
            scriptExector.close();
            // 解析返回结果
            ParseScriptExector.FuncResult funcResult = JSONObject.parseObject(result, ParseScriptExector.FuncResult.class);
            // 更新全局变量
            config.put(methodName, funcResult.getConfig());
            // 返回解析结果
            parseResult = JSONObject.parseObject(funcResult.getOutput(), ParseResult.class);
        } catch (ScriptException | IOException | PolyglotException e) {
            e.printStackTrace();
        }
        return parseResult;
    }

    // 通过platform匹配支持的解析器
    public List<Parser> match(String platform, String name){
        String platformId = SqlUtil.arrayKay(platform);
        return parserMapper.supportActive(platformId, name);
    }

    // 构造入参map
    public Map<String, String> getParams(String paramId, HttpServletRequest request){
        Map<String, String> map = new HashMap<>();
        if (StringUtil.isEmpty(paramId)){
            return map;
        }
        List<ParserParam> parserParams = parserMapper.findParamsByParamId(paramId);
        for (ParserParam parserParam : parserParams){
            String val = getVal(parserParam, request);
            map.put(parserParam.getKey(), val);
        }
        return map;
    }

    // 解析入参的值
    public String getVal(ParserParam parserParam, HttpServletRequest request){
        if (parserParam.getType() == ParserParam.TYPE_VALUE){
            return parserParam.getVal();
        }
        if (parserParam.getType() == ParserParam.TYPE_HEADER){
            return request.getHeader(parserParam.getVal());
        }
        if (parserParam.getType() == ParserParam.TYPE_SQL){
            System.out.println("unsupported type_sql");
        }
        return "";
    }
    public Map<String,String> defaultMap(HttpServletRequest request, String url, VideoInfo videoInfo){
        Map<String, String> map = new HashMap<>();
        if (null == videoInfo){
            map.put("videoInfo", "{}");
        }
        else {
            map.put("videoInfo", EntityUtil.jsonSerializer(videoInfo, false));
        }
        map.put("url", url);
        map.put("remoteAddr", request.getRemoteAddr());
        return map;
    }
    public ParseResult scriptParser(VideoInfo videoInfo, String platform, String url, String name, HttpServletRequest request){
        // 匹配支持的解析器
        List<Parser> parserList = match(platform, name);
        // 获取默认参数
        Map<String, String> defaultParams = defaultMap(request, url, videoInfo);
        for (Parser parser : parserList){
            String scriptName = parser.getScriptName();
            // 获取解析器所需要的入参
            Map<String, String> params = getParams(parser.getParamId(), request);
            params.putAll(defaultParams);
            String input = JSONObject.toJSONString(params);
            // 执行解析方法
            ParseResult result = execFunc(scriptName, parser.getMethod(), input);
            if (ParseResult.isVaild(result) && !result.getRelURL().isEmpty()){
                result.setName(parser.getMethod());
                String type = fileType(result);
                result.setType(type);
                result.setParseUrl(url);
                return result;
            }
        }
        return null;
    }

    private String fileType(ParseResult result){
        if (StringUtil.isEmpty(result.getType()) || "auto".equals(result.getType())){
            String type = URLUtil.fileType(result.getUrl());
            if (type.isEmpty() || type.equals("php")){
                return "hls";
            }
            return type;
        }
        if (result.getType().equals("m3u8")){
            return "hls";
        }
        return result.getType();
    }
}
